/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package communicator;

import base.KN;
import base.KNLink;
import base.TrackForest;
import base.TrackNode;
import base.TrackNode.Echo;
import base.Utilities;
import base.Wave;
import base.WaveEnvironment;
import debug.DebugFrame;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import communicator.message.*;
import trackmsg.EchoMsg;
import trackmsg.TailMsg;
import wave.WaveInterpreter;
/**
 *
 * @author MR.BLACK
 */
public class ProcessClient extends Thread{
        private Socket clientSocket;
        private ObjectInputStream ois;

        public ProcessClient(Socket clientSocket) {
        try {
            this.clientSocket = clientSocket;
            DebugFrame.receivMsg("/*\t\t\t\t\t\t*/Dang doi yeu cau tu: " + clientSocket.getInetAddress().getHostAddress() + "\n");
            ois = new ObjectInputStream(clientSocket.getInputStream());
        } catch (IOException ex) {
            Logger.getLogger(ProcessClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        }

        @Override
        public void run() {
            while (true) {
            try {
                Message msg = (Message) ois.readObject();
                msg.setSourceComputer(clientSocket.getInetAddress().getHostAddress());
                if (msg != null) {
                    DebugFrame.receivMsg("/*\t\t\t\t\t\t*/Co message den tu: " + clientSocket.getInetAddress().getHostAddress() + "\n");
                    processMessage(msg);
                }
            } catch (IOException ex) {
                Utilities.CPPrint("Dong socket nay roi!");
                //Logger.getLogger(ProcessClient.class.getName()).log(Level.SEVERE, null, ex);
                removeThisSocket();
                return;
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(ProcessClient.class.getName()).log(Level.SEVERE, null, ex);
            }
            }
        }
        public void removeThisSocket() {
            int pos = Receiver.listHostAddress.indexOf(clientSocket.getInetAddress().getHostAddress());
            Receiver.listHostAddress.removeElementAt(pos);
            Receiver.listClientOOS.removeElementAt(pos);
        }

        public void processMessage(Message msg) {

            // tao kn link
            if (msg instanceof MsgCreateKNLink) {
                MsgCreateKNLink msgCL = ((MsgCreateKNLink) msg);
                String srcName = msgCL.getSrcNodeName();
                String desName = msgCL.getDesNodeName();
                String scrHost = msgCL.getSourceComputer();
//                String linkAddress = msgCL.getDesLinkAddr();
//                String srcLinkAddress = msgCL.getSrcLinkAddr();
                String linkName = msgCL.getLinkName();
                KN kn = WaveInterpreter.getInstance().getKN();

                kn.addKNLink(Utilities.removeSignOfLink(linkName), -Utilities.linkNameToSign(linkName), kn.getKNNode(desName), srcName, scrHost);
            }

            // tao kn node
            if (msg instanceof MsgCreateKNNode) {
                String nodeName = ((MsgCreateKNNode) msg).getNodeName();
                WaveInterpreter.getInstance().getKN().addKNNode(nodeName);
            }

            // tao track
            if (msg instanceof MsgCreateTrack) {

                MsgCreateTrack msg2 = (MsgCreateTrack) msg;
                String address = msg2.getTrackAddress();
                String enclosedWave = msg2.getEnclosedWave();
                String suspendedTail = msg2.getSuspendedWave();
                WaveEnvironment env = msg2.getWaveEnv();
                String parentAddress = msg2.getParentAddress();
                TrackNode.Type type = msg2.getType();
                TrackNode.Rule rule = msg2.getRule();

                TrackForest trackForest = WaveInterpreter.getInstance().getTrackForest();
                TrackNode trackNode = trackForest.createTrack(address, enclosedWave, suspendedTail, env);
                Utilities.CPPrint("ADDRESS: " + trackNode.getAddress());
                
                trackNode.setType(type);
                trackNode.setRule(rule);
                
                TrackNode nodeParent = trackForest.createRemoteTrack(msg2.getParentAddress(), msg2.getSourceComputer(), msg2.getWaveEnv().clone());

                if (parentAddress!=null && !parentAddress.equals(""))
                    trackNode.setParent(nodeParent);
                Utilities.CPPrint("CHILD: " + trackNode);
                Utilities.CPPrint("PARENT: " + nodeParent);
                DebugFrame.receivMsg("/*\t\t\t\t\t\t\t*/MSgCreateTrack: " + msg2.getSuspendedWave()+"\n");
                DebugFrame.receivMsg("/*\t\t\t\t\t\t\t*/MSgCreateTrack: " + msg2.getWaveEnv()+"\n");

                Wave wave = new Wave(trackNode.getSuspendedTail(), trackNode.getWaveEnv());
                trackNode.suspendedTail(null);
                WaveInterpreter.getInstance().getWaveQueue().incoming(wave);
            }

            // gui msg echo cho track processor
            if (msg instanceof MsgEcho) {
                TrackForest trackForest = WaveInterpreter.getInstance().getTrackForest();
                TrackNode fromTrack = trackForest.getTrackNode(((MsgEcho) msg).getFromTrackAddress());
//                TrackNode toTrack = trackForest.getTrackNode(((MsgEcho) msg).getToTrackAddress());
                
                Echo echo = ((MsgEcho) msg).getEcho();
                EchoMsg echoMsg = new EchoMsg(fromTrack, echo, ((MsgEcho) msg).getWaveEnv());
                WaveInterpreter.getInstance().getTrackQueue().incoming(echoMsg);
            }

            // gui msg tail cho track processor
            if (msg instanceof MsgTail) {
                TrackForest trackForest = WaveInterpreter.getInstance().getTrackForest();
                TrackNode toTrack = trackForest.getTrackNode(((MsgTail) msg).getToTrackAddress());
                String tail = ((MsgTail) msg).getTail();
                boolean keep = ((MsgTail) msg).isKeep();

                TailMsg tailMsg = new TailMsg(toTrack, tail, keep);
                WaveInterpreter.getInstance().getTrackQueue().incoming(tailMsg);
            }

            // neu la MsgWave, lay wave ra nhet wave vao wave queue
            if (msg instanceof MsgWave) {
                Wave wave = ((MsgWave) msg).getWave();
                DebugFrame.receivMsg("/*\t\t\t\t\t\t*/Chuoi wave nhan dc: " + wave.getWaveString() + "\n");
                WaveInterpreter.getInstance().getWaveQueue().incoming(wave);
            }
        }

    }